package com.wbc.demo.CompletableFutureDemo;

import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Stream;

/**
 * @author 389561407@qq.com
 * @version 1.0
 * @since 2022-11-30
 */
public class CompletableFutureDemo {

    public PriceResult getCheapestPlatAndPrice(String product) {
        PriceResult mouBaoPrice = computeRealPrice(HttpRequestMock.getMouBaoPrice(product), HttpRequestMock.getMouBaoDiscounts(product));
        PriceResult mouDongPrice = computeRealPrice(HttpRequestMock.getMouDongPrice(product), HttpRequestMock.getMouDongDiscounts(product));
        PriceResult mouXiXiPrice = computeRealPrice(HttpRequestMock.getMouXiXiPrice(product), HttpRequestMock.getMouXiXiDiscounts(product));
        // 计算并选出实际价格最低的平台
        return Stream.of(mouBaoPrice, mouDongPrice, mouXiXiPrice).min(Comparator.comparingDouble(PriceResult::getRealPrice)).get();
    }

    private PriceResult computeRealPrice(double mouBaoPrice, double mouBaoDiscounts) {
        PriceResult priceResult = new PriceResult();
        priceResult.setRealPrice(mouBaoPrice*mouBaoDiscounts);
        return priceResult;
    }

    public static void main(String[] args) {

        System.out.println("普通执行");
        long l = System.currentTimeMillis();
        CompletableFutureDemo completableFutureDemo = new CompletableFutureDemo();
        PriceResult cheapestPlatAndPrice = completableFutureDemo.getCheapestPlatAndPrice("");
        System.out.println(cheapestPlatAndPrice.getRealPrice());
        System.out.println("普通执行结束，用时："+(System.currentTimeMillis()-l));


        System.out.println("异步执行");
        long ll = System.currentTimeMillis();
        CompletableFutureDemo completableFutureDemo1 = new CompletableFutureDemo();
        PriceResult cheapestPlatAndPrice2 = completableFutureDemo1.getCheapestPlatAndPrice2("");
        System.out.println(cheapestPlatAndPrice2.getRealPrice());
        System.out.println("异步执行结束，用时："+(System.currentTimeMillis()-ll));


        System.out.println("CompletableFuture 异步执行");
        long lll = System.currentTimeMillis();
        CompletableFutureDemo completableFutureDemo11 = new CompletableFutureDemo();
        PriceResult cheapestPlatAndPrice21 = completableFutureDemo11.getCheapestPlatAndPrice3("");
        System.out.println(cheapestPlatAndPrice21.getRealPrice());
        System.out.println("异步执行结束，用时："+(System.currentTimeMillis()-lll));


    }

    //异步
    public PriceResult getCheapestPlatAndPrice2(String product) {
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        Future<PriceResult> mouBaoFuture = executorService.submit(() -> computeRealPrice(HttpRequestMock.getMouBaoPrice(product), HttpRequestMock.getMouBaoDiscounts(product)));
        Future<PriceResult> mouDongFuture = executorService.submit(() -> computeRealPrice(HttpRequestMock.getMouDongPrice(product), HttpRequestMock.getMouDongDiscounts(product)));
        Future<PriceResult> mouXiXiFuture = executorService.submit(() -> computeRealPrice(HttpRequestMock.getMouXiXiPrice(product), HttpRequestMock.getMouXiXiDiscounts(product)));

        executorService.shutdown();
        // 等待所有线程结果都处理完成，然后从结果中计算出最低价
        return Stream.of(mouBaoFuture, mouDongFuture, mouXiXiFuture)
                .map(priceResultFuture -> {
                    try {
                        return priceResultFuture.get(5L, TimeUnit.SECONDS);
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull).min(Comparator.comparingDouble(PriceResult::getRealPrice)).get();
    }

    //CompletableFuture 异步
    public PriceResult getCheapestPlatAndPrice3(String product) {
        CompletableFuture<PriceResult> mouBao = CompletableFuture.supplyAsync(() -> HttpRequestMock.getMouBaoPrice(product))
                .thenCombine(CompletableFuture.supplyAsync(() -> HttpRequestMock.getMouBaoDiscounts(product)), this::computeRealPrice);

        CompletableFuture<PriceResult> mouDong = CompletableFuture.supplyAsync(() -> HttpRequestMock.getMouDongPrice(product))
                .thenCombine(CompletableFuture.supplyAsync(() -> HttpRequestMock.getMouDongDiscounts(product)), this::computeRealPrice);

        CompletableFuture<PriceResult> mouXiXi = CompletableFuture.supplyAsync(() ->  HttpRequestMock.getMouXiXiPrice(product))
                .thenCombine(CompletableFuture.supplyAsync(() -> HttpRequestMock.getMouXiXiDiscounts(product)), this::computeRealPrice);

        // 排序并获取最低价格
        return Stream.of(mouBao, mouDong, mouXiXi)
                .map(CompletableFuture::join).min(Comparator.comparingDouble(PriceResult::getRealPrice))
                .get();
    }
}
